#include "loopbus_hal.h"

#include "bsp.h" // IWYU pragma: keep

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "acommon_err.h"
#include "loopbus.h"
#include "bk9000_device.h"
#include "adc.h"
#include "bgr.h"
#include "gpio.h"
#include "lptim.h"

#define TIMER_RX2_SYNC 0

/* 拉电流控制 */
#define tx_on()        Gpio_SetIO(TX_PORT, TX_PIN)
#define tx_off()       Gpio_ClrIO(TX_PORT, TX_PIN)

extern __IO bk9000_unit_event_t sys_state;

extern const bk9000_sn_t          *sn;
extern volatile uint8_t            shortAddress_temp;
extern volatile bk9000_unit_info_t sys_info;
// extern volatile uint8_t            port_state;
// extern volatile uint8_t            led_disable;

extern volatile uint8_t loopbus_connect;

static volatile uint16_t         leds_pulse_out_tick   = 0;
static leds_set_pulse_callback_t s_leds_pulse_callback = NULL;
static leds_set_ping_callback_t  s_leds_ping_callback  = NULL;

static uint8_t loopbus_busy                            = 0;
LOOPBUS_ADAPTER_EVENT_CFG_INIT_HANDLE();
/**
 * @defgroup 总线定时器相关函数
 *
 * @{
 *
 **/
static void prv_loopbus_tim_init(void);
static void prv_loopbus_tim_start(void);
static void prv_loopbus_tim_stop(void);
/**
 * @} 总线定时器相关函数
 *
 **/

/**
 * @defgroup 总线GPIO相关函数
 *
 * @{
 *
 **/
static void    prv_loopbus_gpio_init(void);
static uint8_t prv_loopbus_gpio_get(loopbus_port_t port);
static uint8_t prv_loopbus_gpio_set(loopbus_port_t port);
static uint8_t prv_loopbus_gpio_reset(loopbus_port_t port);
/**
 * @} 总线GPIO相关函数
 *
 **/

static void prv_pulse_led_set(uint8_t ping);
static void prv_power_ctrl(uint8_t on_off);

/* 心跳灯闪烁时间, 单位: ms(实际915us) */
#define PULSE_LED_COUNT_MAX  (30U)
#define ALARM_LED_COUNT_MAX  (50U)
#define ALARM_LED_COUNT_IDLE (5U)
#define ALARM_LED_BATCH      (8U)
static volatile uint8_t pulse_led_count = 0;

/**
 * @brief 定时器初始化, 总线定时器, 必须初始化为915us
 *
 * @attention 初始化完成后不要开启定时器
 *
 */
static void prv_loopbus_tim_init(void)
{
    Sysctrl_SetPeripheralGate(SysctrlPeripheralLpTim, TRUE);

    stc_lptim_cfg_t stcLptCfg;
    DDL_ZERO_STRUCT(stcLptCfg);

    stcLptCfg.enGate   = LptimGateLow;
    stcLptCfg.enTcksel = LptimXtl;
    stcLptCfg.enCt     = LptimTimerFun; // working as timer
    stcLptCfg.enMd     = LptimMode2;    // reload mode
    stcLptCfg.u16Arr   = 65536 - LOOPBUS_ARR_COUNT;
    Lptim_Init(M0P_LPTIMER, &stcLptCfg);

    Lptim_ClrItStatus(M0P_LPTIMER);          // 清除中断
    Lptim_ConfIt(M0P_LPTIMER, TRUE);         // 打开IE中断
    EnableNvic(LPTIM_IRQn, IrqLevel1, TRUE); // 使能中断
}

/**
 * @brief 开启定时器, 通信已建立, 准备接收数据
 *
 */
static void prv_loopbus_tim_start(void)
{
    loopbus_busy = 1;

    Lptim_ClrItStatus(M0P_LPTIMER);
    Lptim_Cmd(M0P_LPTIMER, TRUE);

    sys_state.isolation = power_isolation_state();

    leds_set_pulse_off();
#if 1
    /* 非报警状态下 或者指示灯标志为置为状态下, 每次通信开始都会关闭指示灯, 避免通信高功耗 */
    if (!sys_state.alarm /* || led_disable */)
        if (s_leds_ping_callback) s_leds_ping_callback(0);
#else 
		
		/* 非报警状态下 或者指示灯标志为置为状态下, 每次通信开始都会关闭指示灯, 避免通信高功耗 */
    if (!sys_state.alarm /* || led_disable */) alarm_led_off();
#endif
}

/**
 * @brief 定时器停止, 通信结束
 *
 */
static void prv_loopbus_tim_stop(void)
{
    // static uint8_t connect = 0;
    Lptim_Cmd(M0P_LPTIMER, FALSE);
    /* 在通信状态下, 无短地址(编址) 和 通信建立 不再自动控制指示灯, 指示灯由总线控制 */
    /* 指示灯控制位继续由led_disable状态位标志, 当清位(0)表示指示灯未屏蔽, 可自主控制. 当置位(1)表示总线已经屏蔽指示灯, 需要由总线控制 */
    /* 当总线确认报警会主动清位(0). 当总线报警超过40个单元后, 总线会主动置为(1)40个之前的报警指示灯 */
    // if (!sys_info.address || (!connect && (connect = LOOPBUS_VECTORS->slave_check_connect()))) led_disable = 1;
    loopbus_connect = !!LOOPBUS_VECTORS->slave_check_connect();
#if 1
    /* 非报警状态下 或者指示灯标志为置为状态下, 每次通信结束都会关闭指示灯, 避免总线持续高功耗 */
    if (!sys_state.alarm /* || led_disable */)
    if (s_leds_ping_callback) s_leds_ping_callback(0);
#else 		
		 /* 非报警状态下 或者指示灯标志为置为状态下, 每次通信结束都会关闭指示灯, 避免总线持续高功耗 */
    if (!sys_state.alarm /* || led_disable */) alarm_led_off();
#endif
    /* 恢复RX1下降沿中断接收, 等待下一次通信建立 */
    Gpio_EnableIrq(RX_1_PORT, RX_1_PIN, GpioIrqFalling);

    loopbus_busy = 0;
}

/**
 * @brief 定时器暂停, 通信不会接收. 可用于同步定时器和短路隔离
 *
 */
static void prv_loopbus_tim_pause(void) 
{ Lptim_Cmd(M0P_LPTIMER, FALSE); }

static void prv_loopbus_tim_resume(void)
{
    Lptim_ClrItStatus(M0P_LPTIMER);
    Lptim_Cmd(M0P_LPTIMER, TRUE);
}

#if TIMER_RX2_SYNC
/**
 * @brief 长帧定时器同步补偿. 减少因为长线负载导致的时间误差
 *
 * @note 非必须实现
 *
 */
static void prv_loopbus_tim_async(void)
{
    Lptim_Cmd(M0P_LPTIMER, FALSE);
    Gpio_EnableIrq(RX_2_PORT, RX_2_PIN, GpioIrqFalling);
}
#endif

/**
 * @brief 总线GPIO初始化
 *
 * @details RX1 -> 总线起始头(0V)检测GPIO,         输入, 无上下拉, 低有效,  默认下降沿中断
 *          RX2 -> 总线数据电平(12V / 8V)检测GPIO, 输入, 无上下拉,         默认无中断
 *          TX1 -> 总线数据响应拉电流(8mA)GPIO,    输出, 无上下拉,  高有效
 *
 * @attention 中断优先级最高
 *
 */
static void prv_loopbus_gpio_init(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    DDL_ZERO_STRUCT(stcGpioCfg);
    stcGpioCfg.enDir      = GpioDirIn;
    stcGpioCfg.enDrv      = GpioDrvL;
    stcGpioCfg.enPu       = GpioPuDisable;
    stcGpioCfg.enPd       = GpioPdDisable;
    stcGpioCfg.enOD       = GpioOdDisable;
    stcGpioCfg.enCtrlMode = GpioAHB;
    Gpio_Init(RX_1_PORT, RX_1_PIN, &stcGpioCfg); // RX_START_PIN
    Gpio_Init(RX_2_PORT, RX_2_PIN, &stcGpioCfg); // RX_DATA_PIN

    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(TX_PORT, TX_PIN, &stcGpioCfg); // TX
    tx_off();

    Gpio_ClearIrq(RX_1_PORT, RX_1_PIN);
    Gpio_ClearIrq(RX_2_PORT, RX_2_PIN);
    EnableNvic(PORTB_IRQn, IrqLevel0, TRUE); // comm IrqLevel higher than RTC
    Gpio_EnableIrq(RX_1_PORT, RX_1_PIN, GpioIrqFalling);
}

/**
 * @brief 总线电压检查
 *
 * @param port 需要检测的端口, see loopbus_port_t
 * @return uint8_t 0
 */
static uint8_t prv_loopbus_gpio_get(loopbus_port_t port)
{
    uint8_t io = 0;
    switch (port)
    {
        case LOOPBUS_PORT_12V: io = !Gpio_GetInputIO(RX_2_PORT, RX_2_PIN); break;
        case LOOPBUS_PORT_0V: io = !Gpio_GetInputIO(RX_1_PORT, RX_1_PIN); break;
        default: break;
    }

    return io;
}

/**
 * @brief 总线拉电流GPIO输出
 *
 * @param port LOOPBUS_PORT_TX
 * @return uint8_t 0
 */
static uint8_t prv_loopbus_gpio_set(loopbus_port_t port)
{
    if (LOOPBUS_PORT_TX == port) Gpio_SetIO(TX_PORT, TX_PIN);

    return 0;
}

/**
 * @brief 总线拉电流GPIO关闭
 *
 * @param port LOOPBUS_PORT_TX
 * @return uint8_t 0
 */
static uint8_t prv_loopbus_gpio_reset(loopbus_port_t port)
{
    if (LOOPBUS_PORT_TX == port) Gpio_ClrIO(TX_PORT, TX_PIN);

    return 0;
}

/**
 * @brief 心跳灯点亮
 *
 */
static void prv_pulse_led_set(uint8_t ping)
{
	
#if 1	
    /* 指示灯输出, 返回值为0标识输出心跳灯 */
    if (s_leds_pulse_callback && s_leds_pulse_callback(leds_pulse_out_tick, ALARM_LED_COUNT_MAX))
    {
        pulse_led_count = ALARM_LED_COUNT_MAX;
    }
    else if (ping /* && (!sys_state.alarm || led_disable) */)
    {
        if (s_leds_ping_callback) s_leds_ping_callback(1);
        pulse_led_count = PULSE_LED_COUNT_MAX;
    }

    //短路隔离周期判断
    if (sys_info.address != 0 && sys_info.address != 255 && power_isolation_state())
    {
        // LOOPBUS_VECTORS->slave_stop_scheduler();
        power_try_peer();
    }
#else
		/* 单元处于不报警、非屏灯情况下(允许亮灯)，输出报警灯，表示心跳 */
    if (sys_state.alarm)
    {
        if (s_leds_pulse_callback) s_leds_pulse_callback(leds_pulse_out_tick, ALARM_LED_COUNT_MAX);
        pulse_led_count = ALARM_LED_COUNT_MAX;
    }
    else if (ping /* && (!sys_state.alarm || led_disable) */)
    {
        alarm_led_on();
        pulse_led_count = PULSE_LED_COUNT_MAX;
    }
		/*尝试恢复短路状态*/
		if(sys_info.address!=0&&sys_info.address!=255&&power_isolation_state())
		{
			//LOOPBUS_VECTORS->slave_stop_scheduler();
			power_try_peer();
		}
		
#endif
}

/**
 * @brief 总线电源控制, 当总线控制电源的时候主动打开
 *
 * @param on_off
 */
static void prv_power_ctrl(uint8_t on_off)
{
    if (on_off) power_on();
    else power_reset_direction();
}

int prv_loopbus_isolation_fsm_handle(uint8_t event, uint8_t *data)
{
    // ACOMMON_LOGD("%d", event);
    switch (event)
    {
        case LOOPBUS_ISOLATION_GET_SHORTADDRESS_TEMP: return shortAddress_temp; /* 获取临时短地址 */
        case LOOPBUS_ISOLATION_GET_SHORTADDRESS: return sys_info.address;       /* 获取短地址 */
        case LOOPBUS_ISOLATION_GET_STATE: return power_isolation_state();       /* 获取隔离状态 */
        case LOOPBUS_ISOLATION_START: ACOMMON_LOGW("loopbus error");detector_state.cheek_on=0;            /* 隔离开始 */
        case LOOPBUS_ISOLATION_SET_ALLOFF: power_isolation_all(); break;        /* 断开全部隔离器 */
        case LOOPBUS_ISOLATION_GET_DIR: return power_check_direction();         /* 检测来电方向 */
        case LOOPBUS_ISOLATION_SET_DIR:
            dir_drv_off();
            power_set_direction();
            break;                                                       /* 打开来电方向的隔离器 */
        case LOOPBUS_ISOLATION_SET_DRVON: power_set_drv_on(); break;     /* 打开方向检测 */
        case LOOPBUS_ISOLATION_TRY: power_try_peer(); break;             /* 尝试闭合对端隔离器 */
        case LOOPBUS_ISOLATION_END:	ACOMMON_LOGD("loopbus stop");detector_state.cheek_on=1;  /* 隔离完成 */
																		break;
    }
    return 0;
}

/****************************************************
**函数名:Event_22_CallBack_Funs
**函数功能:事件发送数据数据回调函数
**函数参数:handle	handle adapter pointer(一般用于事件间的调度切换)
					 cmd   event cmd 
					 ctx		user context()
**函数返回值:无
**备注: ThreeD_Val.Val_flag 每次实时数据保存在结构体中时置位
******************************************************/
static void Event_22_CallBack_Funs(loopbus_adapter_handle_t handle, uint8_t cmd,void *ctx)
{
		uint8_t *Rx_buf;
		int Rx_data_len=0;	
		int16_t		up_data[3]={0};	//感烟雾,感温,Co
		Rx_data_len=LOOPBUS_VECTORS->slave_get_rx_data(handle,&Rx_buf);//接收命令数据
		if(cmd==22)
		{
			if(Rx_buf[0] == sys_info.address)
			{
				switch(Rx_buf[1])
				{
					 /*模拟量上传*/
					case 0xff:  
								//printf("Event 22 smoke[%d] temp[%d] co[%d]\n ",bus_thd_t.thd_t.smoke,bus_thd_t.thd_t.temp,bus_thd_t.thd_t.co);
								up_data[0] = bus_thd_t.thd_t.smoke;
								up_data[1] = bus_thd_t.thd_t.temp;
								up_data[2] = bus_thd_t.thd_t.co;
								LOOPBUS_VECTORS->slave_set_tx_data(handle,(uint8_t *)&up_data[0], sizeof(up_data));
								break;
					/*工作模式*/
					case 0x88:	
								up_data[0] =0;
								up_data[1] = work.modle;
								up_data[2] =0;
								LOOPBUS_VECTORS->slave_set_tx_data(handle,(uint8_t *)&up_data[0], sizeof(up_data));
								break;
					/*报警值*/
					case 0x66:	
								up_data[0] = 0;
								up_data[1] = temp_data.alarm;
								up_data[2] = 0;
								LOOPBUS_VECTORS->slave_set_tx_data(handle,(uint8_t *)&up_data[0], sizeof(up_data));
								break;
					 /*预警值*/
					case 0x06:	up_data[0] = 0;
								up_data[1] = temp_data.prepare_alarm;
								up_data[2] = 0;
								LOOPBUS_VECTORS->slave_set_tx_data(handle,(uint8_t *)&up_data[0], sizeof(up_data));
								break;
				}
			}
		}		
}

/****************************************************
**函数名:Alter_tsdval_Event_24_CallBack
**函数功能:接收修改阈值数据回调函数
**函数参数:handle	handle adapter pointer(一般用于事件间的调度切换)
					 cmd   event cmd 
					 ctx		user context() 联系上下文
**函数返回值:无
**备注: 	Alter_Val.Revise_flag 每次修改阈值时置位
******************************************************/
static void Alter_tsdval_Event_24_CallBack(loopbus_adapter_handle_t handle, uint8_t cmd,void *ctx)
{

//	  uint8_t           ack = 0;
//    uint8_t          *rx_data;
//    unit_class_cfg_t *rx_class;
//    if (LOOPBUS_VECTORS->slave_get_rx_data(ctx, (uint8_t **) (&rx_class)))
//    {
//			
//			if(rx_class->id==sys_info.address){
//			
//							ack      = 1;
//							// FIXME: 在这里修改阈值设置相关变量, 根据情况修改!!!!!!
//							
//							Alter_Val.Smoke_Tsd_Val		=rx_class->type;
//				
//							Alter_Val.Temp_Tsd_Val 		= rx_class->temp.alarm;
//							Alter_Val.Temp_early_Val  = rx_class->temp.pre_alarm;
//							   ACOMMON_LOGD("id[%d] type[%02X]",rx_class->id,
//							                rx_class->type);
//				
//					Alter_Val.Revise_flag=1;	
//					}
//					LOOPBUS_VECTORS->slave_set_ack(ctx, ack);
//			}

		int  Rx_data_len=0;
	  loopbus_cmd_24_rx_data_t *Rx_Data;
    bk9000_unit_info_t const *sys = (bk9000_unit_info_t *) ctx;

		Rx_data_len = LOOPBUS_VECTORS->slave_get_rx_data(handle, (uint8_t **) &Rx_Data);
		if(cmd==24)
		{
		
			if(Rx_Data->address==sys_info.address)
			{	
					memcpy((void *)sys->data,(void *)&Rx_Data->cfg,sizeof(bk9000_unit_detector_thd_t));		
					Alter_Val.Smoke_Tsd_Val	=Rx_Data->cfg.calc_mode ;
					Alter_Val.Temp_Tsd_Val 	=((Rx_Data->cfg.thd.smoke.alarm &0x00ff)>>8)|((Rx_Data->cfg.thd.smoke.alarm &0xff00)<<8);
					Alter_Val.Temp_early_Val 	=((Rx_Data->cfg.thd.smoke.pre_alarm &0x00ff)>>8)|((Rx_Data->cfg.thd.smoke.pre_alarm &0xff00)<<8);;
					ACOMMON_LOGD("id[%d] type[%02X] temp_a[0x%04X] temp_pa[0x%04X]",Rx_Data->address,
							        Rx_Data->cfg.calc_mode,Rx_Data->cfg.thd.smoke.alarm,Rx_Data->cfg.thd.smoke.pre_alarm);		
					Alter_Val.Revise_flag=1;	
					LOOPBUS_VECTORS->slave_set_ack(handle, 1); //返回应答				
			}	
		}else { LOOPBUS_VECTORS->slave_set_ack(handle,0);}	
		
}




/**
 * @brief 总线初始化
 *
 */
void loopbus_hal_init(void)
{
    loopbus_cfg_t cfg = {0};

    loopbus_led_tick_update();

    /* 总线定时器相关函数 */
    cfg.tim.init   = prv_loopbus_tim_init;
    cfg.tim.start  = prv_loopbus_tim_start;
    cfg.tim.stop   = prv_loopbus_tim_stop;
    cfg.tim.pause  = prv_loopbus_tim_pause;
    cfg.tim.resume = prv_loopbus_tim_resume;

#if TIMER_RX2_SYNC
    cfg.tim.async = prv_loopbus_tim_async;
#endif

    /* 总线GPIO相关函数 */
    cfg.gpio.init           = prv_loopbus_gpio_init;
    cfg.gpio.get            = prv_loopbus_gpio_get;
    cfg.gpio.set            = prv_loopbus_gpio_set;
    cfg.gpio.reset          = prv_loopbus_gpio_reset;

    cfg.mode                = LOOPBUS_MODE_SLAVE;
    cfg.isolation_enable    = LOOPBUS_ENABLE;

    loopbus_t const *lp_ctx = LOOPBUS_VECTORS;
    ACOMMON_LOGD("loopbus version %s", lp_ctx->get_version());

    /* bk9000解析器相关 */
    loopbus_adapter_cfg_t adapter_cfg = {0};
    adapter_cfg.sn                    = (uint8_t *) sn->id;           /* 单元长地址 */
    adapter_cfg.info                  = (loopbus_info_t *) &sys_info; /* 单元信息 */
    adapter_cfg.shortAddress_temp     = &shortAddress_temp;           /* 单元临时短地址 */
    adapter_cfg.sys_state             = (uint16_t *) &sys_state;      /* 单元状态(报警/故障)变量地址 */
    // adapter_cfg.port_state            = &port_state;                  /* 单元输出端口控制 */
    adapter_cfg.ping_callback         = prv_pulse_led_set; /* 单元闪灯控制 */
    adapter_cfg.isolator_ctrl         = prv_power_ctrl;    /* 单元隔离和电源控制, 编址使用 */
    // adapter_cfg.led_disable           = &led_disable;                 /* 指示灯屏蔽和控制 */

#ifdef LPDEF_EVENT_EN
    /* 注册其他命令 */ 
		LOOPBUS_ADAPTER_EVENT_CFG_HANDLE_EXTERN();  
		adapter_cfg.event_cfg_list_start = &lp_event_cfg_start;
		adapter_cfg.event_cfg_list_end   = &lp_event_cfg_end;	
		
		loopbus_adapter_handle_t adapter_hanlde = LOOPBUS_VECTORS->adapter_init(adapter_cfg);
		cfg.adapter_hanlde                      = adapter_hanlde;			
	
#else 
	 /* bk9000解析器初始化, 必须在总线初始化前完成 */
    loopbus_adapter_handle_t adapter_hanlde = LOOPBUS_VECTORS->adapter_init(adapter_cfg);
  
		loopbus_register_event_cfg_t  Reg_Event_Id22_Cfg={0};
		Reg_Event_Id22_Cfg.cmd_data_len				=		2; 	//上传数据命令数据长度
		Reg_Event_Id22_Cfg.return_data_len			=		6; 	//返回数据长度
		Reg_Event_Id22_Cfg.event_callback 			=		Event_22_CallBack_Funs;		//事件回调函数
		LOOPBUS_VECTORS->slave_register_event_id(adapter_hanlde,22,Reg_Event_Id22_Cfg);//注册事件id
		
		loopbus_register_event_cfg_t  Reg_Event_Id24_Cfg={0};
		Reg_Event_Id24_Cfg.cmd_data_len				=		14;
		Reg_Event_Id24_Cfg.return_data_len			=		0;
		Reg_Event_Id24_Cfg.event_callback			=		Alter_tsdval_Event_24_CallBack;
		LOOPBUS_VECTORS->slave_register_event_id(adapter_hanlde,24,Reg_Event_Id24_Cfg);//注册事件id 24
		
		cfg.adapter_hanlde                      = adapter_hanlde;	
		 
#endif
  
    /* 总线错误事件回调函数 */
    // extern void loopbus_error_event(loopbus_handle_t handle, int error_event, void *ctx);
    // cfg.error_interrupt = loopbus_error_event;

    /* 总线隔离处理实现函数 */
    // extern void loopbus_isolation_proc(loopbus_handle_t handle);
    // cfg.isolation_proc = loopbus_isolation_proc;

    LOOPBUS_VECTORS->isolation_init(prv_loopbus_isolation_fsm_handle);

    /* 总线初始化 */
    LOOPBUS_VECTORS->init(&cfg);;
}

void loopbus_led_pulse_register(leds_set_pulse_callback_t callback) { s_leds_pulse_callback = callback; }
void loopbus_led_ping_register(leds_set_ping_callback_t callback) { s_leds_ping_callback = callback; }

/**
 * @brief 主动开启总线的低功耗定时器
 *
 */
void loopbus_tim_start(void) { prv_loopbus_tim_start(); }

/**
 * @brief 主动通过回路上报设备(单元)状态
 *
 */
void loopbus_state_report(void) { LOOPBUS_VECTORS->slave_state_report(NULL); }

/**
 * @brief 获取新命令事件
 *
 * @return int
 */
loopbus_adapter_event_id_t loopbus_get_new_cmd_event(loopbus_adapter_event_msg_t *msg)
{
    if (LOOPBUS_VECTORS->slave_adapter_new_event) return LOOPBUS_VECTORS->slave_adapter_new_event(NULL, msg);

    return LOOPBUS_ADAPTER_EVENT_NULL;
}

void loopbus_led_tick_update(void)
{
    leds_pulse_out_tick = (ALARM_LED_COUNT_MAX + ALARM_LED_COUNT_IDLE) * (sys_info.address % ALARM_LED_BATCH);
}

int loopbus_is_busy(void) { return loopbus_busy; }

/**
 * @defgroup 硬件中断函数开始
 *
 * @{
 *
 **/

/**
 * @brief 低功耗定时器中断
 *
 */
void LpTim_IRQHandler(void)
{
    Lptim_ClrItStatus(M0P_LPTIMER);

    LOOPBUS_VECTORS->slave_tick_handler();

    if (!(--pulse_led_count) && (!sys_state.alarm /* || led_disable */))
    {
        if (s_leds_ping_callback) s_leds_ping_callback(0);
    }
#if SHYS_CONFIG_OUTSIDE
		
			if(!loopbus_connect)
			{
				if(bsp_power_lose_t.dowm_timer_cnt<2050)
							bsp_power_lose_t.dowm_timer_cnt++;
				if(!bsp_power_lose_t.pd_start)
							bsp_power_lose_t.pd_start=1;
			}	
#endif
}

/**
 * @brief GPIOB中断
 *
 */
void PortB_IRQHandler(void)
{
    if (TRUE == Gpio_GetIrqStatus(RX_1_PORT, RX_1_PIN))
    {
        Gpio_DisableIrq(RX_1_PORT, RX_1_PIN, GpioIrqFalling);
        Gpio_ClearIrq(RX_1_PORT, RX_1_PIN);
        LOOPBUS_VECTORS->slave_start_scheduler();
    }
#if TIMER_RX2_SYNC
    if (TRUE == Gpio_GetIrqStatus(RX_2_PORT, RX_2_PIN))
    {
        Gpio_DisableIrq(RX_2_PORT, RX_2_PIN, GpioIrqFalling);
        Gpio_ClearIrq(RX_2_PORT, RX_2_PIN);
        LOOPBUS_VECTORS->slave_async_scheduler();
    }
#endif
}
/**
 * @} 硬件中断函数结束
 *
 **/










